package com.sh.rbac.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sh.rbac.domain.converter.OperationLogConverter;
import com.sh.rbac.domain.dto.operationLog.OperationLogQueryDTO;
import com.sh.rbac.domain.entity.OperationLog;
import com.sh.rbac.domain.vo.operationLog.OperationLogEeVO;
import com.sh.rbac.domain.vo.operationLog.OperationLogVO;
import com.sh.rbac.exception.CustomException;
import com.sh.rbac.handler.OperationLogCellStyleHandler;
import com.sh.rbac.mapper.OperationLogMapper;
import com.sh.rbac.service.OperationLogService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

/**
 * @author lucky
 * @description 针对表【sys_operation_log(操作日志记录表)】的数据库操作Service实现
 * @createDate 2024-07-07 17:50:48
 */
@Slf4j
@Service
public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, OperationLog>
        implements OperationLogService {

    @Override
    public Page<OperationLogVO> getPage(Long current, Long limit, OperationLogQueryDTO operationLogQueryDTO) {
        // 创建 page 对象，传递当前页, 每页记录数
        Page<OperationLog> page = new Page<>(current, limit);

        // 条件参数
        String operationUsername = operationLogQueryDTO.getUsername();
        String operationModule = operationLogQueryDTO.getOperationModule();
        Integer operationType = operationLogQueryDTO.getOperationType();
        Integer operationStatus = operationLogQueryDTO.getOperationStatus();

        String startTime = null;
        String endTime = null;
        if (operationLogQueryDTO.getOperationTimes() != null) {
            startTime = operationLogQueryDTO.getOperationTimes()[0];
            endTime = operationLogQueryDTO.getOperationTimes()[1];
        }

        // 构建条件
        LambdaQueryWrapper<OperationLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(operationUsername), OperationLog::getOperationUsername, operationUsername)
                .like(StrUtil.isNotBlank(operationModule), OperationLog::getOperationModule, operationModule)
                .eq(operationType != null, OperationLog::getOperationType, operationType)
                .eq(operationStatus != null, OperationLog::getOperationStatus, operationStatus)
                .between(StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime), OperationLog::getOperationTime, startTime, endTime);

        // 根据修改时间倒序
        queryWrapper.orderByDesc(OperationLog::getOperationTime);

        // 查询数据
        Page<OperationLog> operationLogPage = baseMapper.selectPage(page, queryWrapper);

        // 转换数据
        Page<OperationLogVO> operationLogVO = new Page<>();
        operationLogVO.setTotal(operationLogPage.getTotal());
        operationLogVO.setSize(operationLogPage.getSize());
        operationLogVO.setCurrent(operationLogPage.getCurrent());
        operationLogVO.setRecords(OperationLogConverter.INSTANCE.convertToOperationLogVOList(operationLogPage.getRecords()));
        operationLogVO.setPages(operationLogPage.getPages());

        return operationLogVO;
    }

    @Override
    public void exportData(Integer startCount, Integer endCount, HttpServletResponse response) {
        try {
            List<OperationLog> operationLogs = baseMapper.selectList(new QueryWrapper<OperationLog>().last("limit " + startCount + "," + endCount));
            List<OperationLogVO> operationLogVO = OperationLogConverter.INSTANCE.convertToOperationLogVOList(operationLogs);

            // 设置 HTTP 响应内容类型
            response.setContentType("application/vnd.vnd.ms-excel");
            // 设置字符 HTTP 请求字符编码为 utf-8
            response.setCharacterEncoding("utf-8");
            // 设置文件名
            String fileName = URLEncoder.encode("操作日志-" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_FORMAT) + RandomUtil.randomNumbers(5), StandardCharsets.UTF_8);
            // 设置 HTTP 请求响应头
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

            log.info("导出的数据 => {}", operationLogVO);
            // 写入数据
            EasyExcel.write(response.getOutputStream())
                    .head(OperationLogEeVO.class)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet("操作日志")
                    .registerWriteHandler(new OperationLogCellStyleHandler())
                    .doWrite(operationLogVO);
        } catch (Exception e) {
            throw new CustomException("数据导出失败!");
        }
    }
}




